package cn.wizzer.app.crown.modules.services.impl;


import cn.wizzer.app.crown.modules.models.CrownConfig;
import cn.wizzer.app.crown.modules.models.CrownLeague;
import cn.wizzer.app.crown.modules.models.CrownLeagueResult;
import cn.wizzer.app.crown.modules.models.CrownOrder;
import cn.wizzer.app.crown.modules.models.constant.CrownConstant;
import cn.wizzer.app.crown.modules.models.enums.MatchTypeEnum;
import cn.wizzer.app.crown.modules.models.enums.SettleStatusEnum;
import cn.wizzer.app.crown.modules.services.BKSettleService;
import cn.wizzer.app.crown.modules.services.CrownConfigService;
import cn.wizzer.app.crown.modules.services.CrownLeagueService;
import cn.wizzer.app.crown.modules.services.FTSettleService;
import cn.wizzer.app.crown.modules.services.order.CrownOrderService;
import cn.wizzer.app.crown.modules.services.result.LeagueResultService;
import cn.wizzer.framework.base.Result;
import cn.wizzer.framework.base.exceptions.BizException;
import cn.wizzer.framework.base.service.BaseServiceImpl;
import cn.wizzer.framework.base.service.CommonDBService;
import cn.wizzer.framework.page.Pagination;
import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.google.common.base.Joiner;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.pager.Pager;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.log.Log;
import org.nutz.log.Logs;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@IocBean(args = {"refer:dao"})
@Service(interfaceClass = CrownLeagueService.class)
public class CrownLeagueServiceImpl extends BaseServiceImpl<CrownLeague> implements CrownLeagueService {
    public CrownLeagueServiceImpl(Dao dao) {
        super(dao);
    }

    @Reference
    @Inject
    private CrownOrderService orderService;

    @Inject
    private CrownConfigService crownConfigService;

    @Inject
    private LeagueResultService leagueResultService;

    @Inject
    private BKSettleService bkSettleService;
    @Inject
    private FTSettleService ftSettleService;
    @Inject
    private CommonDBService commonDBService;

    private static final Log log = Logs.get();

    @Override
    public CrownLeague queryByLeagueInfo(MatchTypeEnum type, String league, String championName, Date dateTime) {
        Cnd cnd = Cnd.where("type", "=", type).and("league", "=", league)
                .and("champion_name", "=", championName).and("date_time", "=", dateTime);
        return this.fetch(cnd);
    }


    @Override
    @Aop(TransAop.REPEATABLE_READ)
    public void updateResult(CrownLeague league) {
        List<CrownLeagueResult> subResults = league.getSubResults();
        // 版本号从0开始
        int version = 0;
        // 查询出该场联赛下的赛果集合
        Cnd cnd = Cnd.where("league_id", "=", league.getId());
        // 如果league的version不为空，说明是从前端传入的，查询最新的version
        if (null != league.getVersion()) {
            cnd.and("version", "=", league.getVersion());
        }
        // 取最新版本的赛果集合
        List<CrownLeagueResult> oldResults = leagueResultService.query(cnd);
        // 如果已经有赛果
        if (CollectionUtils.isNotEmpty(oldResults)) {
            // 当赛果不相同时，插入新赛果，version值+1
            if (!ListUtils.isEqualList(oldResults, subResults)) {
                version = oldResults.get(0).getVersion() + 1;
            } else {
                Result.breakWith("请勿填入相同的赛果");
            }
        }
        // 入库赛果
        for (CrownLeagueResult subResult : subResults) {
            subResult.setLeagueId(league.getId());
            subResult.setVersion(version);
        }
        // 设置联赛版本
        league.setVersion(version);
        // 赛果详情入库
        leagueResultService.fastInsert(subResults);
        // 更新联赛状态
        this.update(league);
        // 如果联赛版本大于0说明版本变化，重新结算
        if (version > 0) {
            orderService.reSettle(league);
        }
    }

    @Override
    public Pagination results(String start, String end, Pager pager, String sportType) {
        // 分页查询联赛信息
        Sql sql = Sqls.create("SELECT * FROM crown_league $condition ");
        Sql countSql = Sqls.create("SELECT count(1) FROM crown_league $condition ");
        Cnd cnd = Cnd.where("date_time", ">=", start)
                .and("date_time", "<=", end)
                .and("type", "=", sportType)
                .and(Cnd.exps("stage", "=", CrownConstant.FINISHED)
                        .or("stage", "=", CrownConstant.OTHER));
        sql.setCondition(cnd);
        countSql.setCondition(cnd);

        Pagination pagination = this.listPage(pager.getPageNumber(), pager.getPageSize(), sql, countSql);
        // 查询每条联赛赛果详情
        pagination.getList(CrownLeague.class).forEach(league -> {
            List<CrownLeagueResult> results = leagueResultService.query(league.getId());
            List<String> collect = results.stream().map(CrownLeagueResult::getWinner).collect(Collectors.toList());
            league.setResults(Joiner.on(",").join(collect));
        });
        return pagination;
    }

    @Override
    public void settleChampion(CrownLeague league) {
        // 更新冠军赛果
        this.updateResult(league);
        // 查询出关联该联赛的订单
        Sql sql = Sqls.create("SELECT o.* FROM crown_order_detail od LEFT JOIN crown_order o on o.id = od.order_id");
        sql.appendSourceSql("WHERE od.game_id = @gameId and o.status = @orderStatus");
        sql.setParam("gameId", league.getId()).setParam("orderStatus", SettleStatusEnum.WAIT_SETTLE);
        List<CrownOrder> orderList = commonDBService.list(CrownOrder.class, sql.toString());
        if (CollectionUtils.isEmpty(orderList)) {
            throw new BizException("没有待结算的订单");
        }
        // 遍历集合逐条结算
        for (int i = 0; i < orderList.size(); i++) {
            CrownOrder order = orderList.get(i);
            try {
                if (MatchTypeEnum.FOOTBALL.equals(order.getMatchType())) {
                    ftSettleService.settle(order);
                } else {
                    bkSettleService.settle(order);
                }
            } catch (BizException e) {
                log.info(e.getRemand());
            }
        }
    }

    @Override
    public void crawlLeagueResult(Long startTime, Long endTime) {
        // 获取爬虫账号
        CrownConfig crownConfig = crownConfigService.syncOne("手动获取赛果任务");
        if (crownConfig != null) {
            log.info("准备开始任务:" + crownConfig);
            try {
                // 一天的毫秒值
                long oneDayMilliSecond = 24 * 60 * 60 * 1000;
                // 计算要爬取的天数
                long dayNum = (endTime - startTime) / oneDayMilliSecond + 1;
                // 如果不限制天数爬虫程序可能会超时
                if (dayNum > 10) {
                    throw new BizException("最多选择10天进行爬取");
                }
                // 处理日期格式
                String start = DateFormatUtils.format(startTime, "yyyy-MM-dd HH:mm:ss");
                String end = DateFormatUtils.format(endTime, "yyyy-MM-dd HH:mm:ss");
                // 查询日期范围内所有状态不是finished的赛事
                Cnd cnd = Cnd.NEW();
                cnd.where().andBetween("date_time", start, end)
                        .and("stage", "!=", "finished").and("stage", "!=", "other");
                List<CrownLeague> list = this.query(cnd);
                for (int i = 0; i < list.size(); i++) {
                    leagueResultService.crawler(list.get(i), crownConfig);
                }
            } finally {
                // 获取账号，判断是否为空，以防账号已经被清除
                crownConfigService.release(crownConfig);
            }
        } else {
            throw new BizException("没有可用的账号");
        }
    }
}
